package com.smedi.ismedi.constructionproject.core.port.adapter.restful;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smedi.ismedi.constructionproject.api.dto.request.*;
import com.smedi.ismedi.constructionproject.api.dto.response.ProjectBasicResponse;
import com.smedi.ismedi.constructionproject.api.dto.response.ProjectTreeResponse;
import com.smedi.ismedi.constructionproject.api.dto.response.resp.ProjectDetailResp;
import com.smedi.ismedi.constructionproject.api.dto.response.resp.ProjectResp;
import com.smedi.ismedi.constructionproject.api.dto.response.resp.ProjectWithDingResp;
import com.smedi.ismedi.constructionproject.api.feign.RemoteConstructionProjectFeignApi;
import com.smedi.ismedi.constructionproject.core.application.command.*;
import com.smedi.ismedi.constructionproject.core.application.query.ProjectAssignmentQueryService;
import com.smedi.ismedi.constructionproject.core.application.query.ProjectBasicQueryService;
import com.smedi.ismedi.constructionproject.core.application.query.vo.ProjectBasicVo;
import com.smedi.ismedi.constructionproject.core.application.query.vo.ProjectDetailVo;
import com.smedi.ismedi.constructionproject.core.application.query.vo.ProjectWithDingVo;
import com.smedi.ismedi.constructionproject.core.application.service.ConstructionProjectApplicationService;
import com.smedi.ismedi.constructionproject.core.domain.aggregatemodel.Project;
import com.smedi.ismedi.constructionproject.core.domain.aggregatemodel.ProjectBasic;
import com.smedi.ismedi.constructionproject.core.port.adapter.restful.convert.AdapterConverter;
import com.smedi.ismedi.constructionproject.core.port.adapter.service.OrganizationRemoteApiService;
import com.smedi.ismedi.organization.api.dto.response.HrOrganizationResponse;
import com.smedi.ismedi.web.starter.common.PaginationData;
import com.smedi.ismedi.web.starter.common.ResponseData;
import com.smedi.ismedi.web.starter.util.DozerUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @Author: xulinjun
 * @Date: 2021-6-21 10:16
 */
@Slf4j
@RestController
@AllArgsConstructor
public class ConstructionProjectController implements RemoteConstructionProjectFeignApi {
    private final DozerUtil dozerUtil;
    private final AdapterConverter adapterConverter;

    private final ConstructionProjectApplicationService constructionProjectApplicationService;

    private final OrganizationRemoteApiService organizationRemoteApiService;

    private final ProjectBasicQueryService projectBasicQueryService;

    private final ProjectAssignmentQueryService projectAssignmentQueryService;

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<ProjectBasicResponse> postSaveProjectInfo(ProjectBasicRequest projectBasicRequest) {
        ProjectBasicCommand projectBasicCommand = dozerUtil.convertor(projectBasicRequest, ProjectBasicCommand.class);
        ProjectBasic projectBasic = constructionProjectApplicationService.saveProjectBasicInfo(projectBasicCommand);
        return new ResponseData<ProjectBasicResponse>().success(dozerUtil.convertor(projectBasic, ProjectBasicResponse.class));
    }

    @Override
    public ResponseData<Boolean> updateProjectInfo(ProjectBasicUpdateRequest projectBasicUpdateRequest) {
        ProjectBasicUpdateCommand projectBasicUpdateCommand = dozerUtil.convertor(projectBasicUpdateRequest, ProjectBasicUpdateCommand.class);
        return new ResponseData<Boolean>().success(constructionProjectApplicationService.updateProjectBasicInfo(projectBasicUpdateCommand));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData> getQueryProjectPagination(Long offset, Long pageSize, String projectName, String projectCode, String projectManager, Long hrOrganizationId, boolean containHrOrganizationChildren) {
        IPage pagination = projectBasicQueryService.getProjectPagination(offset, pageSize, projectName, projectCode, projectManager, hrOrganizationId, containHrOrganizationChildren);
        PaginationData paginationResponse = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(paginationResponse);
    }

    @Override
    public ResponseData<ProjectBasicResponse> getQueryProjectBasicView(Long projectId) {
        ProjectBasicVo projectBasicVo = projectBasicQueryService.getProjectBasicView(projectId);
        return new ResponseData<ProjectBasicResponse>().success(dozerUtil.convertor(projectBasicVo, ProjectBasicResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryProjectBasicView(String provinceName) {
        List<ProjectBasicVo> projectBasicVoList = projectBasicQueryService.getProjectBasicView(provinceName);
        return new ResponseData<ProjectBasicResponse>().success(dozerUtil.convertor(projectBasicVoList, ProjectBasicResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<Boolean> getCheckProjectAvailable(Long projectId) {
        return new ResponseData<Boolean>().success(constructionProjectApplicationService.validateProject(projectId));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<Boolean> getCheckHrOrganizationHasProject(Long hrOrganizationId) {
        return new ResponseData<Boolean>().success(constructionProjectApplicationService.validateHrOrgHasProject(hrOrganizationId));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData> getQueryProjectManagementInfoPagination(Long offset, Long pageSize, String projectName, String projectCode, String projectManager, Long hrOrganizationId, String supervisionUnit, String projectStatus, String projectCategory, String contractDurationBegin, String contractDurationEnd) {
        IPage pagination = projectBasicQueryService.getProjectManagementInfoPagination(offset, pageSize, projectName, projectCode, projectManager, hrOrganizationId, supervisionUnit, projectStatus, projectCategory, contractDurationBegin, contractDurationEnd);

        PaginationData paginationResponse = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(paginationResponse);
    }

    @Override
    public ResponseData<PaginationData> getQueryProjectManagementInfoPaginationForMobile(Long offset, Long pageSize, String projectName, String projectCode, String projectManager, Long hrOrganizationId, String supervisionUnit, String projectStatus, String projectCategory, String contractDurationBegin, String contractDurationEnd, String epcType) {
        IPage pagination = projectBasicQueryService.getProjectManagementInfoPaginationForMobile(offset, pageSize, projectName, projectCode, projectManager, hrOrganizationId, supervisionUnit, projectStatus, projectCategory, contractDurationBegin, contractDurationEnd, epcType);

        PaginationData paginationResponse = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(paginationResponse);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryAvailableProjectBasicList() {
        List<ProjectBasicVo> list = projectBasicQueryService.getAvailableProjectList();

        return new ResponseData<List<ProjectBasicResponse>>().success(dozerUtil.convertor(list, ProjectBasicResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryAvailableProjectBasicListWithToken() {
        List<ProjectBasicVo> list = projectBasicQueryService.getAvailableProjectListWithToken();

        return new ResponseData<List<ProjectBasicResponse>>().success(dozerUtil.convertor(list, ProjectBasicResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<ProjectTreeResponse> getProjectTreeWithHrOrganizations() {
        Map<Long, List<ProjectBasicVo>> maps = projectBasicQueryService.getProjectTree();

        // 获取根节点
        HrOrganizationResponse root = organizationRemoteApiService.getHrOrganizationRoot();
        ProjectTreeResponse projectTreeResponse = new ProjectTreeResponse()
                .setHrOrganizationCode(root.getOrganizationCode())
                .setHrOrganizationShortName(root.getShortName())
                .setHrOrganizationName(root.getFullName())
                .setHrOrganizationId(root.getHrOrganizationId())
                .setRoot(true);

        // 获取企业组织id
        List<Long> hrOrganizationIds = new ArrayList<>();
        for (Map.Entry<Long, List<ProjectBasicVo>> entry : maps.entrySet()) {
            if (!hrOrganizationIds.contains(entry.getKey())) {
                hrOrganizationIds.add(entry.getKey());
            }
        }

        // 调用获取组织结果
        List<HrOrganizationResponse> hrOrganizationResponses = organizationRemoteApiService.getHrOrganizationByHrOrganizationIds(hrOrganizationIds);
        List<ProjectTreeResponse> children = new ArrayList<>();
        // 循环拼接数据
        for (Map.Entry<Long, List<ProjectBasicVo>> entry : maps.entrySet()) {
            Optional<HrOrganizationResponse> optional = hrOrganizationResponses.stream().filter(i -> i.getHrOrganizationId().equals(entry.getKey())).findFirst();
            optional.ifPresent(hrOrganizationResponse -> children.add(new ProjectTreeResponse()
                    .setHrOrganizationCode(hrOrganizationResponse.getOrganizationCode())
                    .setHrOrganizationName(hrOrganizationResponse.getFullName())
                    .setHrOrganizationId(hrOrganizationResponse.getHrOrganizationId())
                    .setHrOrganizationShortName(hrOrganizationResponse.getShortName())
                    .setRoot(false)
                    .setProjectBasics(dozerUtil.convertor(entry.getValue(), ProjectBasicResponse.class))));
        }

        projectTreeResponse.setProjectTrees(children);

        return new ResponseData<ProjectTreeResponse>().success(projectTreeResponse);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<Boolean> deleteProjectAllInfos(Long projectId) {
        constructionProjectApplicationService.deleteProjectAllInfos(projectId);
        return new ResponseData<Boolean>().success(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryProjectBasicListByHrOrganizationIds(List<Long> hrOrganizationIds) {
        List<ProjectBasicResponse> responses = dozerUtil.convertor(projectBasicQueryService.getProjectBasicListByHrOrganizationIds(hrOrganizationIds), ProjectBasicResponse.class);
        return new ResponseData<List<ProjectBasicResponse>>().success(responses);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryProjectBasicListByPersonId(Long personId) {
        List<Long> projectIds = projectAssignmentQueryService.getDistinctProjectIdsByPersonId(personId);
        List<ProjectBasicVo> projectBasicVos = projectBasicQueryService.getProjectBasicViewSimpleList(projectIds);
        return new ResponseData<List<ProjectBasicResponse>>().success(dozerUtil.convertor(projectBasicVos, ProjectBasicResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryProjectBasicListByHrOrganizationId(Long hrOrganizationId) {
        List<Long> hrOrganizationIds = organizationRemoteApiService.getHrOrganizationChildrenOrgIdList(hrOrganizationId);
        List<ProjectBasicResponse> responses = dozerUtil.convertor(projectBasicQueryService.getProjectBasicListByHrOrganizationIds(hrOrganizationIds), ProjectBasicResponse.class);
        return new ResponseData<List<ProjectBasicResponse>>().success(responses);
    }

    @Override
    public ResponseData<List<ProjectBasicResponse>> getQueryProjectBasicListByApp(String appSearch,List<Long> ids) {
        List<ProjectBasicResponse> responses = dozerUtil.convertor(projectBasicQueryService.getQueryProjectBasicListByApp(appSearch,ids), ProjectBasicResponse.class);
        return new ResponseData<List<ProjectBasicResponse>>().success(responses);
    }

    @Override
    public ResponseData<ProjectBasicResponse> postSaveVividProgress(Long projectId, int vividProgress, LocalDate vividProgressUpdatedDate) {
        ProjectBasic projectBasic = constructionProjectApplicationService.postSaveVividProgress(projectId, vividProgress, vividProgressUpdatedDate);
        ProjectBasicResponse response = dozerUtil.convertor(projectBasic, ProjectBasicResponse.class);
        return new ResponseData<>().success(response);
    }

    @Override
    public ResponseData<ProjectBasicResponse> postSaveRegionPicture(Long projectId, String regionPicture) {
        ProjectBasic projectBasic = constructionProjectApplicationService.postSaveRegionPicture(projectId, regionPicture);
        ProjectBasicResponse response = dozerUtil.convertor(projectBasic, ProjectBasicResponse.class);
        return new ResponseData<>().success(response);
    }

    @Override
    public ResponseData<ProjectBasicResponse> postSaveOrganizationPicture(Long projectId, String organizationPicture) {
        ProjectBasic projectBasic = constructionProjectApplicationService.postSaveOrganizationPicture(projectId, organizationPicture);
        ProjectBasicResponse response = dozerUtil.convertor(projectBasic, ProjectBasicResponse.class);
        return new ResponseData<>().success(response);
    }

    @Override
    public ResponseData<ProjectBasicResponse> postSaveEntrustBook(Long projectId, String entrustBook) {
        ProjectBasic projectBasic = constructionProjectApplicationService.postSaveEntrustBook(projectId, entrustBook);
        ProjectBasicResponse response = dozerUtil.convertor(projectBasic, ProjectBasicResponse.class);
        return new ResponseData<>().success(response);
    }

    @Override
    public ResponseData<ProjectBasicResponse> postSaveMonitorType(Long projectId, String monitorType, String monitorTypeNote) {
        ProjectBasic projectBasic = constructionProjectApplicationService.postSaveMonitorType(projectId, monitorType, monitorTypeNote);
        ProjectBasicResponse response = dozerUtil.convertor(projectBasic, ProjectBasicResponse.class);
        return new ResponseData<>().success(response);
    }

    @Override
    public ResponseData<ProjectResp> getProjectOne(ProjectOneQueryRequest projectOneQueryRequest) {
        ProjectOneQueryCommand projectOneQueryCommand = dozerUtil.convertor(projectOneQueryRequest, ProjectOneQueryCommand.class);
        Project projects = projectBasicQueryService.getProjectOne(projectOneQueryCommand);
        return new ResponseData<>().success(dozerUtil.convertor(projects, ProjectResp.class));
    }

    @Override
    public ResponseData<List<ProjectResp>> getProjectList(ProjectListQueryRequest projectListQueryRequest) {
        ProjectListQueryCommand projectListQueryCommand = dozerUtil.convertor(projectListQueryRequest, ProjectListQueryCommand.class);
        List<Project> projects = projectBasicQueryService.getProjectList(projectListQueryCommand);
        return new ResponseData<>().success(dozerUtil.convertor(projects, ProjectResp.class));
    }

    @Override
    public ResponseData<PaginationData<ProjectDetailResp>> getProjectDetailPage(ProjectPageQueryRequest projectPageQueryRequest) {
        ProjectPageQueryCommand projectPageQueryCommand = dozerUtil.convertor(projectPageQueryRequest, ProjectPageQueryCommand.class);
        Page<ProjectDetailVo> projectDetailPage = projectBasicQueryService.getProjectDetailPage(projectPageQueryCommand);
        return new ResponseData<>().success(adapterConverter.projectPageToProjectRespPaginationData(projectDetailPage));
    }

    @Override
    public ResponseData<List<ProjectDetailResp>> getProjectDetailList(ProjectListQueryRequest projectListQueryRequest) {
        ProjectListQueryCommand projectListQueryCommand = dozerUtil.convertor(projectListQueryRequest, ProjectListQueryCommand.class);
        List<ProjectDetailVo> projectDetails = projectBasicQueryService.getProjectDetailList(projectListQueryCommand);
        return new ResponseData<>().success(dozerUtil.convertor(projectDetails, ProjectDetailResp.class));
    }

    @Override
    public ResponseData<List<ProjectResp>> getProjectListWithoutToken(ProjectListQueryRequest projectListQueryRequest) {
        ProjectListQueryCommand projectListQueryCommand = dozerUtil.convertor(projectListQueryRequest, ProjectListQueryCommand.class);
        List<Project> projects = projectBasicQueryService.getProjectList(projectListQueryCommand);
        return new ResponseData<>().success(dozerUtil.convertor(projects, ProjectResp.class));
    }

    @Override
    public ResponseData<Long> updateByName(ConstructionProjectUpdateRequest constructionProjectUpdateRequest) {
        ConstructionProjectUpdateCommand command = dozerUtil.convertor(constructionProjectUpdateRequest, ConstructionProjectUpdateCommand.class);
        return new ResponseData<Long>().success(constructionProjectApplicationService.updateProjectByName(command));
    }

    @Override
    public ResponseData<List<ProjectWithDingResp>> getProjectResponseDataByOrgId(Long orgId) {
        List<ProjectWithDingVo> projectWithDingVos = projectBasicQueryService.getProjectVosByOrgId(orgId);
        List<ProjectWithDingResp> resps = dozerUtil.convertor(projectWithDingVos, ProjectWithDingResp.class);
        return new ResponseData<>().success(resps);
    }

    @Override
    public ResponseData<ProjectWithDingResp> getProjectWithDing(Long id) {
        ProjectWithDingVo vo = projectBasicQueryService.getProjectWithDingVoById(id);
        ProjectWithDingResp resp = dozerUtil.convertor(vo, ProjectWithDingResp.class);
        return new ResponseData<>().success(resp);
    }

    @Override
    public ResponseData<Integer> getProjectCount(ProjectCountQueryRequest projectCountQueryRequest) {
        ProjectCountQueryCommand projectCountQueryCommand = dozerUtil.convertor(projectCountQueryRequest, ProjectCountQueryCommand.class);
        return new ResponseData<Integer>().success(projectBasicQueryService.getProjectCount(projectCountQueryCommand));
    }
}
